home *** CD-ROM | disk | FTP | other *** search
/ AppleScript - The Beta Release / AppleScript - The Beta Release.iso / Documentation / develop / Apple Event Objects and You / Apple Event Objects (code) / cWindow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-08  |  19.6 KB  |  674 lines  |  [TEXT/KAHL]

  1.  
  2.  
  3. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  4. /*                                                                                   */
  5. /*    This file contains the code for implementing the cWindow AE object.                */
  6. /*                                                                                   */
  7. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  8.  
  9. /* Include any container or parent class headers here */
  10. #include "AEPackObject.h"
  11. #include "AEObjects.h"
  12. #include "AERegistry.h"
  13. #include <packages.h>
  14. #include "ScriptScrap.h"
  15. #include "Prototypes.h"
  16.  
  17.  
  18.  
  19. pascal OSErr WindowFromNullAccessor ( DescType desiredClass,
  20.             const AEDesc *container, DescType containerClass, DescType keyForm,
  21.             const AEDesc *keyData, AEDesc *returnedToken, long refCon )
  22. {
  23.     WindowPtr    currWindow = FrontWindow();
  24.     long        count = 1;
  25.     long        windowNum = 0;
  26.     OSErr        err;
  27.     Boolean        getAll;
  28.     AEDesc        scratchToken;
  29.     Str255        nameKey = "", windowName = "";
  30.     long        nameLength;
  31.     Boolean        found = false;
  32.  
  33.     switch (keyForm) {
  34.  
  35.         case formAbsolutePosition:
  36.             getAll = false;
  37.             /* Extract the key's value, handling any of the special constant values */
  38.             err = Win_ConvertAbsKey(keyData, &windowNum, &getAll);
  39.             if (err != noErr) return err;
  40.  
  41.             if (getAll)
  42.                 return errAEEventFailed;    /* We don't handle multiple windows at one time */
  43.             
  44.             currWindow = FindIndexedWindow(windowNum);
  45.             if (currWindow == NULL)
  46.                 return errAENoSuchObject;
  47.             
  48.             /* Now, build a token containing this window */
  49.             BuildWindowToken(currWindow, desiredClass, count, returnedToken);
  50.         break;
  51.  
  52.         case formName:
  53.             /* Get the number of bytes in the specified window name */
  54.             nameLength = GetHandleSize(keyData->dataHandle);
  55.             if (nameLength > 255) return errAENoSuchObject;
  56.  
  57.             /* Move the name into a Pascal-style string */
  58.             nameKey[0] = (char)nameLength;
  59.             BlockMove(*(keyData->dataHandle), &nameKey[1], nameLength);
  60.  
  61.             /* Now, search for a window with the same name */
  62.             count = 1;
  63.             while ((currWindow != NULL) && !found) {
  64.                 GetWTitle(currWindow, windowName);
  65.                 found = IUEqualString(nameKey, windowName) == 0;
  66.                 if (found) break;    /* Exit the while loop */
  67.                 count++;
  68.                 currWindow = (WindowPtr)(((WindowPeek)currWindow)->nextWindow);
  69.             }
  70.             if (!found) return errAENoSuchObject;
  71.  
  72.             /* If the window was found, then construct a token to represent it */
  73.             BuildWindowToken(currWindow, desiredClass, count, returnedToken);
  74.         break;
  75.  
  76.         default:
  77.             return errAEEventNotHandled;
  78.     }
  79.  
  80.     return noErr;
  81. }    /*  WindowFromNull */
  82.  
  83.  
  84. /* Property from object accessors */
  85. pascal OSErr PropertyFromWindowAccessor ( DescType desiredClass,
  86.             const AEDesc *container, DescType containerClass, DescType keyForm,
  87.             const AEDesc *keyData, AEDesc *returnedToken, long refCon )
  88. {
  89.     OSErr        err = noErr;
  90.     Boolean        ok;
  91.     DescType    requestedProperty;
  92.     
  93.     if ((keyForm != formPropertyID) || (keyData->descriptorType != typeType))
  94.         return errAECantSupplyType;
  95.  
  96.     if ((container->descriptorType != cWindow) && (container->descriptorType != cDocument))
  97.         return errAETypeError;
  98.  
  99.     requestedProperty = **(DescType**)keyData->dataHandle;
  100.     
  101.     /* Check to see if this is a legal property code for this object class */
  102.     ok = false;
  103.     switch (requestedProperty) {
  104.         /*  read-only properties common to cWindow and cDocument */
  105.         case pBestType:
  106.         case pClass:
  107.         case pDefaultType:
  108.             ok = true;
  109.         break;
  110.  
  111.         /*  read-only properties unique to cWindow */
  112.         case pHasCloseBox:
  113.         case pHasTitleBar:
  114.         case pIsFloating:
  115.         case pIsModal:
  116.         case pIsResizable:
  117.         case pIsZoomable:
  118.             if (containerClass == cWindow) 
  119.                 ok = true;
  120.         break;
  121.  
  122.         /*  read-only properties unique to a cDocument */
  123.         case pIsModified:
  124.             if (containerClass == cDocument) 
  125.                 ok = true;
  126.         break;
  127.         
  128.         /*  modifiable properties common to cWindow and cDocument */
  129.         case pName:
  130.             ok = true;
  131.         break;
  132.         
  133.         /*  modifiable properties unique to cWindow */
  134.         case pBounds:
  135.         case pIndex:
  136.         case pIsZoomed:
  137.         case pSelection:
  138.         case pVisible:
  139.             if (containerClass == cWindow) 
  140.                 ok = true;
  141.         break;
  142.     }
  143.     
  144.     if (ok) {
  145.         /* Copy the container and convert it into a property token */
  146.         err = AEDuplicateDesc(container, returnedToken);
  147.         if (err == noErr) {
  148.             tokenFlags(*returnedToken) = kPropToken;
  149.             tokenPropCode(*returnedToken) = requestedProperty;
  150.         }
  151.         return err;
  152.     } else 
  153.         return errAENoSuchObject; /*  We really want "not a property", but that isn't defined  */
  154. } /* PropertyFromWindowAccessor */
  155.  
  156.  
  157. /* === Handy utilities === */
  158.  
  159. long CountWindows()
  160. {
  161.     WindowPtr    currWindow = FrontWindow();
  162.     long        count = 0;
  163.  
  164.     while (currWindow != NULL) {
  165.         count++;
  166.         currWindow = (WindowPtr)(((WindowPeek)currWindow)->nextWindow);
  167.     }
  168.     return count;
  169. } /* CountWindows */
  170.  
  171.  
  172. long GetWindowIndex(WindowPtr theWindow)
  173. /*  Given a windowPtr, return its index (frontmost window = 1, next back = 2, etc.) */
  174. {
  175.     WindowPtr    currWindow = FrontWindow();
  176.     long        count = 1;
  177.  
  178.  
  179.     while (currWindow != theWindow) {
  180.         if (currWindow == NULL) 
  181.             return 0;
  182.         count++;
  183.         currWindow = (WindowPtr)(((WindowPeek)currWindow)->nextWindow);
  184.     }
  185.     return count;
  186. } /* GetWindowIndex */
  187.  
  188.  
  189. WindowPtr FindIndexedWindow(long index)
  190. /* This routine searches the window list for the window with the specified index */
  191. /* This is used in conjunction with Win_CreateElement to indicate where the new  */
  192. /* window should go. */
  193. {
  194.     WindowPeek    result;
  195.     
  196.     if (index <= 0)
  197.         result = (WindowPeek)-1;    /* Special value for "in front of the frontmost window" */
  198.     else {
  199.         result = (WindowPeek)FrontWindow();
  200.         while ((index > 1) && (result != NULL)) {
  201.             if (result->visible)
  202.                 --index;
  203.             result = result->nextWindow;
  204.         }
  205.     }
  206.     return (WindowPtr)result;
  207. }
  208.  
  209.  
  210. OSErr Win_ConvertAbsKey(const AEDesc *keyData, long *index, Boolean *getAll)
  211. /* This routine extracts the value from a formAbsolutePosition key, including the special */
  212. /* "first", "last", any", "all", and "middle" constants.  */
  213. {
  214.     long     numWindows = CountWindows();
  215.     long    rawIndex;
  216.     
  217.     /*  There are 3 flavors of formAbsolutePosition key -- typeIndexDescriptor (position 1, 2, 3…), */
  218.     /*  typeRelativeDescriptor (1 from the beginning, 2 from the beginning, 1 from the end (-1), */
  219.     /*  2 from the end (-2), etc.) or typeAbsoluteOrdinal (first, last, middle, any, and all). */
  220.     /*  We'll handle each of these forms in turn */
  221.     
  222.     *getAll = FALSE;
  223.     rawIndex = **((long**)keyData->dataHandle);        /* Get the number out of the key */
  224.     switch (keyData->descriptorType) {
  225.         case typeRelativeDescriptor:
  226.             if (rawIndex < 0)
  227.                 /* A negative value means "the Nth object from the end", */
  228.                 /* i.e. -1 == the last object */
  229.                 rawIndex = numWindows + rawIndex + 1;
  230.             /*  Otherwise the number is positive, and we treat it like a regular index */
  231.         break;
  232.         
  233.         case typeAbsoluteOrdinal:
  234.             if (rawIndex == kAEFirst)
  235.                 rawIndex = 1;
  236.             else if (rawIndex == kAELast)
  237.                 rawIndex = numWindows;
  238.             else if (rawIndex == kAEMiddle)
  239.                 rawIndex = numWindows / 2;
  240.             else if (rawIndex == kAEAny) {
  241.                 if (numWindows <= 1)        /*  0 or 1 windows */
  242.                     rawIndex = numWindows;
  243.                 else
  244.                     /* Get a random number between 1 and numWindows */
  245.                     rawIndex = 1 + ((unsigned long)Random() * (numWindows - 1)) >> 16;
  246.                 }
  247.             else if (rawIndex == kAEAll)
  248.                 *getAll = TRUE;
  249.         break;
  250.         
  251.         case typeIndexDescriptor:
  252.             /*  The proper number is already in "rawIndex" */
  253.         break;
  254.     }
  255.     
  256.     /* Make sure the returned value is in range */
  257.     *index = (rawIndex < 1) ? 1: rawIndex;    /*  If rawIndex is 0 or negative, return 1  */
  258.     if (rawIndex > numWindows)                /*  Make sure it's not too large either */
  259.         return errAENoSuchObject;
  260.     else
  261.         return noErr;
  262. } /* Win_ConvertAbsKey */
  263.  
  264.  
  265. void BuildWindowToken(const WindowPtr theWindow, DescType desiredClass, long index, AEDesc *theToken)
  266. {
  267.     AEDesc    nullContainer = {'null', NULL};
  268.     wiHand    info = (wiHand)GetWRefCon(theWindow);
  269.     
  270.     theToken->descriptorType = desiredClass;
  271.     theToken->dataHandle = NewHandleClear(sizeof(ourToken));
  272.     tokenDispatchClass(*theToken) = desiredClass;
  273.     tokenFlags(*theToken) = kObjectToken;
  274.     tokenObjectIndex(*theToken) = index;
  275.     tokenWindow(*theToken) = theWindow;
  276.     tokenFRefNum(*theToken) = (*info)->fRefNum;
  277.     
  278. }
  279.  
  280.  
  281. /* Token resolvers -- read, write, insert, delete */
  282.  
  283. /* Individual event handlers */
  284.  
  285. OSErr Win_CreateElement(AppleEvent *message, AppleEvent *reply, DescType insertionPos, /* <- this is normally the refCon */
  286.                      AEDesc *token, AEDesc *replyObject)
  287. {
  288.     OSErr        err              = noErr;
  289.     AEDesc        nullContainer = {'null', 0L};
  290.     AEDesc        keyData          = {'null', 0L};
  291.     WindowPtr    behindWindow;
  292.     long        index;
  293.     WindowPtr    doc_wind      = 0L;
  294.     
  295.     /* We've been asked for a new window or document. So create one in the */
  296.     /* appropriate layer on the screen */
  297.     switch (insertionPos) {
  298.         case kAEBeginning:
  299.             behindWindow = (WindowPtr)-1L;
  300.             index = 1;
  301.         break;
  302.     
  303.         case kAEEnd:
  304.             behindWindow = NULL;
  305.             index = CountWindows();
  306.         break;
  307.         
  308.         case kAEBefore:
  309.             if (token->dataHandle == NULL)
  310.                 return errAETypeError;
  311.             index = tokenObjectIndex(*token);
  312.             behindWindow = FindIndexedWindow(index - 1);
  313.         break;
  314.         
  315.         case kAEAfter:
  316.             if (token->dataHandle == NULL)
  317.                 return errAETypeError;
  318.             index = tokenObjectIndex(*token) + 1;
  319.             behindWindow = FindIndexedWindow(index);
  320.         break;
  321.         
  322.         case kAEReplace:
  323.         default:
  324.             return errAEEventFailed;    /*  We won't allow a new window to replace an existing one */
  325.     }
  326.     
  327.     NewDisplayWindow(NULL); // <<< Potential addition: get a file alias from the "data" parameter
  328.     doc_wind = FrontWindow();
  329.     if ( IsValidPointer ( doc_wind ) )
  330.         AECreateDesc(typeIndexDescriptor, (Ptr)&index, sizeof(index), &keyData);
  331.     else
  332.         err = MemError();
  333.  
  334.     if (keyData.dataHandle != 0L) {
  335.         /* Package everything up into an object specifier.  */
  336.         err = CreateObjSpecifier(cWindow, &nullContainer, formAbsolutePosition, &keyData, true, replyObject);
  337.     }
  338.     return err;
  339. } /* Win_CreateElement */
  340.  
  341.  
  342. OSErr Win_GetData(AppleEvent *message, AppleEvent *reply, long refcon,
  343.                 AEDesc *token, AEDesc *replyObject)
  344. {
  345.     return Win_ReadTokenData(token, replyObject);
  346. } /* Win_GetData */
  347.  
  348.  
  349. OSErr Win_SetData(AppleEvent *message, AppleEvent *reply, long refcon,
  350.                 AEDesc *token, AEDesc *replyObject)
  351. {
  352.     AEDesc    theData;
  353.     OSErr    err;
  354.  
  355.     err = AEGetKeyDesc(message, keyAEData, typeWildCard, &theData);
  356.     if (err == noErr) {
  357.         /* We don't handle passing in the data as an object specifier yet */
  358.         if (theData.descriptorType = typeObjectSpecifier) {
  359.             return errAECantHandleClass;
  360.         }
  361.         err = Win_WriteTokenData(token, &theData);
  362.         (void)AEDisposeDesc(&theData);
  363.     }
  364.     return err;
  365. } /* Win_SetData */
  366.  
  367.  
  368. OSErr Win_Close(AppleEvent *message, AppleEvent *reply, long refcon,
  369.                 AEDesc *token, AEDesc *replyObject)
  370. {
  371.     WindowPtr    theWindow = tokenWindow(*token);
  372.  
  373.     CloseAWindow(theWindow);
  374.     return noErr;
  375.  
  376. } /* Win_Close */
  377.  
  378.  
  379. OSErr Win_ReadTokenData(const AEDesc *theToken, AEDesc *tokenContents)
  380. {
  381.     DescType    scratchType;
  382.     Boolean        scratchBool;
  383.     WindowPtr    theWindow;
  384.     DescType    propCode,
  385.                 objClass;
  386.     OSErr        err            = noErr;
  387.     AEDesc        keyData,
  388.                 nullDesc    = {'null', NULL};
  389.     AEDesc        scratchDesc;
  390.     long        documentNumber;
  391.     
  392.     /*  Get the thing pointed to by a property or object token */
  393.     theWindow = tokenWindow(*theToken);
  394.     objClass = tokenDispatchClass(*theToken);
  395.     if (tokenFlags(*theToken) & kPropToken) {
  396.         /* Return any readable properties */
  397.         propCode = tokenPropCode(*theToken);
  398.         
  399.         switch (propCode) {
  400.             case pClass: 
  401.                 return AECreateDesc(typeType, (Ptr)&objClass, sizeof(objClass), tokenContents);
  402.             break;
  403.             
  404.             case pBestType:
  405.             case pDefaultType:
  406.                 scratchType = typeObjectSpecifier;
  407.                 return AECreateDesc(typeType, (Ptr)&scratchType, sizeof(scratchType), tokenContents);
  408.             break;
  409.             
  410.             case pHasTitleBar:
  411.                 /*  Yes Virginia, there is a Title Bar */
  412.                 scratchBool = true;
  413.                 return AECreateDesc(typeBoolean, (Ptr)&scratchBool, sizeof(scratchBool), tokenContents);
  414.             break;
  415.             
  416.             case pHasCloseBox:
  417.             case pIsFloating:
  418.             case pIsModal:
  419.             case pIsResizable:
  420.             case pIsZoomable:
  421.             case pIsZoomed:
  422.                 /*  None of the above properties are true */
  423.                 scratchBool = false;
  424.                 return AECreateDesc(typeBoolean, (Ptr)&scratchBool, sizeof(scratchBool), tokenContents);
  425.             break;
  426.             
  427.             case pVisible:
  428.                 /*  We'll have to check the window… */
  429.                 scratchBool = ((WindowPeek)theWindow)->visible;
  430.                 return AECreateDesc(typeBoolean, (Ptr)&scratchBool, sizeof(scratchBool), tokenContents);
  431.             break;
  432.             
  433.             case pIsModified:
  434.                 /* Our file is automatically saved any time a change is made, so this is */
  435.                 /* always false. */
  436.                 scratchBool = false;
  437.                 return AECreateDesc(typeBoolean, (Ptr)&scratchBool, sizeof(scratchBool), tokenContents);
  438.             break;
  439.             
  440.             case pName: {
  441.                 /* Get the title of the selected window and return that */
  442.                 Str255    windowName;
  443.                 
  444.                 GetWTitle(theWindow, windowName);
  445.                 return AECreateDesc(typeChar, (Ptr)&windowName[1], *windowName, tokenContents);
  446.             } break;
  447.             
  448.             case pSelection: {
  449.                 /* If we have a current selection, return an object specifier for it. */
  450.                 /* Otherwise, return null */
  451.                 wiHand    info = (wiHand)GetWRefCon(theWindow);
  452.                 AEDesc    nullContainer = {typeNull, NULL};
  453.                 AEDesc    keyData, docContainer;
  454.                 long    index;
  455.                 
  456.                 if ((*info)->numEntries == 0) {
  457.                     /* There's no selection, so return a null descriptor */
  458.                     *tokenContents = nullContainer;
  459.                 } else {
  460.                     /* Return an object specifier for the currently visible entry */
  461.                     /* The specifier will be "entry n of document m" */
  462.                     index = GetWindowIndex(theWindow);
  463.                     err = CreateOffsetDescriptor(index, &keyData);
  464.                     if (err != noErr) return err;
  465.                     err = CreateObjSpecifier(cDocument, &nullContainer, formAbsolutePosition, &keyData, true, &docContainer);
  466.                     /* We don't have to dispose of the container or key data because CreateObjSpecifier does that for us */
  467.                     if (err == noErr) {
  468.                         /* We have the "document m" part, now complete the object specifier */
  469.                         index = (*info)->currEntryNum;
  470.                         err = CreateOffsetDescriptor(index, &keyData);
  471.                         if (err == noErr) {
  472.                             err = CreateObjSpecifier(cEntry, &docContainer, formAbsolutePosition, &keyData, true, tokenContents);
  473.                         }
  474.                     }
  475.                 }
  476.             } break;
  477.             
  478.         }
  479.     }
  480.     else
  481.         if (tokenFlags(*theToken) & kObjectToken) {
  482.             /* The default representation for a window or document is an object specifier */
  483.             long    index;
  484.             AEDesc    nullContainer = {typeNull, NULL};
  485.             
  486.             /* We want an object specifier of the form "document m" */
  487.             index = GetWindowIndex(theWindow);
  488.             err = CreateOffsetDescriptor(index, &keyData);
  489.             if (err == noErr)
  490.                 err = CreateObjSpecifier(cDocument, &nullContainer, formAbsolutePosition, &keyData, true, tokenContents);
  491.         }
  492.     else
  493.         err = errAEEventFailed;
  494.     
  495.     return err;
  496. }
  497.  
  498.  
  499. OSErr Win_WriteTokenData(const AEDesc *theToken, const AEDesc *data)
  500. {
  501.     OSErr        err            = noErr;
  502.     long        numItems, index;
  503.     AEDesc        currItemDesc = {'null', NULL};
  504.     AEKeyword     theAEKeyword;
  505.     DescType    propCode;
  506.     AEDesc        coercedData = {'null', NULL};
  507.     WindowPtr    theWindow;
  508.     
  509.     propCode = tokenPropCode(*theToken);
  510.     theWindow = tokenWindow(*theToken);
  511.     
  512.     switch(propCode) {
  513.     
  514.         case pBounds: {
  515.             /*  Change the bounds of the window. The data should be a QDRect */
  516.             Rect    newBounds;
  517.             
  518.             err = AECoerceDesc(data, typeQDRectangle, &coercedData);
  519.             if (err != noErr) {
  520.                 newBounds = **(Rect**)coercedData.dataHandle;
  521.                 MoveWindow(theWindow, newBounds.left, newBounds.top, false);
  522.                 SizeWindow(theWindow, newBounds.right - newBounds.left, 
  523.                                       newBounds.bottom - newBounds.top, true);
  524.             }
  525.         } break;
  526.  
  527.         case pIndex: {
  528.             /*  Move this window behind another one */
  529.             long        newIndex, currIndex;
  530.             WindowPtr    windowInFront;
  531.             
  532.             err = AECoerceDesc(data, typeLongInteger, &coercedData);
  533.             if (err != noErr) {
  534.                 newIndex = **(short**)coercedData.dataHandle;
  535.                 currIndex = GetWindowIndex(theWindow);
  536.                 if (newIndex == currIndex) break;        /*  We're done, so exit this case */
  537.                 
  538.                 /*  Otherwise, we have to move the window */
  539.                 /*  Since all we have is a "send behind" call, we have to calculate the */
  540.                 /*  number of the window we should sit behind. The rules are as follows: */
  541.                 /*    1) If we're moving into position 1, use SelectWindow */
  542.                 /*      2) If we're moving to a higher index # (further back), move behind */
  543.                 /*         the window with the destination index number */
  544.                 /*      3) Otherwise, move behind the window with an index of (destination - 1) */
  545.                 
  546.                 if (newIndex == 1)
  547.                     SelectWindow(theWindow);
  548.                 else {
  549.                     if (newIndex > currIndex) {
  550.                         windowInFront = FindIndexedWindow(newIndex);
  551.                         SendBehind(theWindow, windowInFront);
  552.                         HiliteWindow(theWindow, false);
  553.                     } else {
  554.                         windowInFront = FindIndexedWindow(newIndex - 1);
  555.                         SendBehind(theWindow, windowInFront);
  556.                         /*  required code to keep the window manager happy in this one case */
  557.                         PaintOne((WindowPeek)theWindow, ((WindowPeek)theWindow)->strucRgn);
  558.                         CalcVis((WindowPeek)theWindow);
  559.                         SelectWindow(FrontWindow());    /*  This is simple paranoia, but I want to make sure all of the activates happen correctly */
  560.                     }
  561.                     HiliteWindow(theWindow, false);
  562.                     SelectWindow(FrontWindow());    /*  This is simple paranoia, but I want to make sure all of the activates happen correctly */
  563.                 }
  564.             }
  565.         } break;
  566.  
  567.         case pIsZoomed:
  568.             /*  This window isn't zoomable, so this is a no-op */
  569.         break;
  570.  
  571.         case pName: {
  572.             /*  Change the name of the window (and the name of the file) */
  573.             /* We don't do this */
  574.             return errAEWriteDenied;
  575.         } break;
  576.  
  577.         case pSelection: {
  578.             /*  Set the current selection under program control. */
  579.             /* We don't do this */
  580.             return errAEWriteDenied;
  581.         } break;
  582.  
  583.         case pVisible: {
  584.             /*  Show or hide the window. The data should be a char with the value 0 or 1 */
  585.             /*  (Since pointers are declared as char*, we don't need to cast) */
  586.             err = AECoerceDesc(data, typeBoolean, &coercedData);
  587.             if (err != noErr) {
  588.                 if (**coercedData.dataHandle != 0)
  589.                     ShowWindow(theWindow);
  590.                 else
  591.                     HideWindow(theWindow);
  592.             }
  593.         } break;
  594.  
  595.         default:
  596.             err = errAENotModifiable;
  597.     }
  598.     if (coercedData.dataHandle != NULL) 
  599.         (void)AEDisposeDesc(&coercedData);
  600.     return err;
  601. }
  602.  
  603.  
  604. OSErr Win_AE_Dispatcher(const AppleEvent *message, AppleEvent *reply, long refCon,
  605.                         AEEventClass classID, AEEventID eventID,
  606.                         const AEDesc *ospec, const AEDesc *token)
  607. {
  608.     OSErr    err = noErr;
  609.     AEDesc    replyDesc = {'null', 0L};
  610.  
  611.     if (classID == kAECoreSuite) {
  612.         switch (eventID) {
  613.             case kAECreateElement:
  614.                 err =  Win_CreateElement(message, reply, refCon, token, &replyDesc);
  615.             break;
  616.  
  617.             case kAEClose:
  618.             case kAEDelete:
  619.                 err =  Win_Close(message, reply, refCon, token, &replyDesc);
  620.             break;
  621.  
  622.             case kAEGetData:
  623.                 err =  Win_GetData(message, reply, refCon, token, &replyDesc);
  624.             break;
  625.  
  626.             case kAEGetDataSize: {
  627.                 /*  We'll do this one by executing "Get Data" and then returning the  */
  628.                 /*  size of the information. This is not necesarily the most efficient */
  629.                 /*  way to do things if your returned data is large. */
  630.                 
  631.                 AEDesc    tempDesc = {'null', NULL};
  632.                 long    dataSize;
  633.                 
  634.                 err = Win_GetData(message, reply, refCon, token, &tempDesc);
  635.                 if (tempDesc.dataHandle != NULL) {
  636.                     dataSize = GetHandleSize(tempDesc.dataHandle);
  637.                     (void)AECreateDesc(typeLongInteger, (Ptr)&dataSize, sizeof(dataSize), &replyDesc);
  638.                     (void)AEDisposeDesc(&tempDesc);
  639.                 }
  640.             }
  641.             break;
  642.  
  643.             case kAESetData:
  644.                 err =  Win_SetData(message, reply, refCon, token, &replyDesc);
  645.             break;
  646.  
  647.             /* Events that we don't do */
  648.             case kAESave:                    /* Changes are saved automatically */
  649.             case kAERevert:
  650.             case kAEPrint:                    /* Sorry, no printing */
  651.             case kAEClone:                    /* These other events are left up to you! */
  652.             case kAECountElements:
  653.             case kAEDoObjectsExist:
  654.             case kAEGetClassInfo:
  655.             case kAEMove:
  656.             case kAEOpen:
  657.             default:
  658.                 err = errAEEventNotHandled ;
  659.         }
  660.     }
  661.     else
  662.         err = errAEEventNotHandled;
  663.  
  664.     /* See if we need to return anything */
  665.     if ((err == noErr) && (replyDesc.descriptorType != 'null')
  666.             && (reply->descriptorType != 'null')) {    /* Note: if the other side didn't ask for a reply, this could be a null desc */
  667.             err = AEPutParamDesc(reply, keyDirectObject, &replyDesc);
  668.             (void)AEDisposeDesc(&replyDesc);
  669.     }
  670.  
  671.     return err;
  672. } /* Win_AE_Dispatcher */
  673.  
  674.